"""海康"""
from loguru import logger
import httpx
import orjson
from psycopg2 import extras
from flask import Blueprint, request, g, current_app
from dao.experts_face import add_experts_face_info, update_experts_face_info
from dao.cabinet import modify_updated_at, info
from dao.project import not_checkout, project_status
from util.response import response
from util import (handle_cabinet, inspect_handle_cabinet,
                  handle_auth, handle_room, picture_check,
                  get_person_info, appointment_records,
                  single_person_add, order_register,
                  visitor_sign_out_func, signout_handle_room,
                  appointment_cancel, visitor_appointment_func,
                  cabinet_status, inspect_cabinet_status)
import util.validation as validation

hk_api = Blueprint('hk_api', __name__)


@hk_api.route("/api/picture/check", methods=['POST'])
def picture_check_post():
    """人脸评分"""
    data = request.get_json()
    if not data.get("facePicBinaryData"):
        return response(422, "字段 facePicBinaryData 不能为空", {})

    res = picture_check(data["facePicBinaryData"])
    return response(res['code'], res['msg'], res['data'])


@hk_api.route("/api/resource/personInfo", methods=['POST'])
def resource_person_info():
    """查询人员详情"""
    data = request.get_json()
    if not data.get('id_card'):
        return response(422, "字段 id_card 不能为空", {})

    res = get_person_info({"paramName": "certificateNo", "paramValue": [data["id_card"]]})

    if res['code'] != '0':
        return response(res['code'], res['msg'], res['data'])

    return response(res['code'], res['msg'], res['data']['list'])


@hk_api.route("/api/visitor/appointment", methods=['POST'])
def visitor_appointment():
    """添加访客预约"""  
    try:
        data = request.get_json()
        _, msg = validation.validate_fields(data, {"personId", "phone_number", "faceData", "room_ids", "role_id"})
        if msg:
            return response(422, msg, {})

        res = get_person_info({"paramName": "personId", "paramValue": [data["personId"]]})

        if res['code'] != '0':
            return response(res['code'], res['msg'], res['data'])

        result = res['data']['list'][0]

        logger.bind(log_type='signin').info("🏒🏒🏒|" + ("-" * 50)  + "|" + result["certificateNo"] + "|" + ("-" * 50) + "|")

        params = {
            "receptionistId": result['personId'],
            "pageNo": 1,
            "pageSize": 1000
        }
    
        records = appointment_records(params)
        
        if records['code'] == '0' and records['data'] and records['data']['list']:
            record = records['data']['list'][-1]
            if 'appointRecordId' in record:
                resp = appointment_cancel([record['appointRecordId']])
                logger.bind(log_type='signin').info({"id_card": result["certificateNo"], "action": "取消预约", "data": resp})
            if 'orderId' in record:
                resp = visitor_sign_out_func(record)
                logger.bind(log_type='signin').info({"id_card": result["certificateNo"], "action": "访客签退", "data": resp})

        # 检查 redis 中有没有删除人脸的key
                
        with g.db_conn.cursor(cursor_factory=extras.RealDictCursor) as cursor:

            query = """
                SELECT 
                    "position", "row", "column", "position_id", ip_address 
                FROM 
                    cabinet
                JOIN 
                    persons 
                ON persons.box_id = cabinet.id 
                WHERE 
                    persons.id_card = %s
            """
            cursor.execute(query, (result["certificateNo"],))
            box = cursor.fetchone()
            if box:

                lock_key = f"{current_app.config['CABINET_LOCK']}{result['certificateNo']}_{box['position']}_{box['position_id']}_{box['row']}_{box['column']}_{box['ip_address']}"
                g.redis_conn.delete(lock_key)

                key = f"{current_app.config['CABINET_DELETE']}{result['certificateNo']}_{box['ip_address']}"
                g.redis_conn.delete(key)
                
        resp = visitor_appointment_func(data, result)
    
    
        logger.bind(log_type='signin').info({"id_card": result["certificateNo"], "action": "请求参数", 'data': {'role_id': data['role_id'], 'personId': data['personId'], 'phone': data.get('phone_number')}})
        logger.bind(log_type='signin').info({"id_card": result["certificateNo"], "action": "访客预约", "data": resp})


        if 'appointmentInfoList' in resp['data'] and resp['data']['appointmentInfoList']:

            with g.db_conn.cursor(cursor_factory=extras.RealDictCursor) as cursor:
                query = """
                    UPDATE 
                        project_person_relation ppr
                    SET 
                        status = 4
                    FROM 
                        persons p 
                    WHERE 
                        p.id = ppr.person_id AND p.id_card = %s AND ppr.status = 3
                """
                cursor.execute(query, (result["certificateNo"],))
                g.db_conn.commit()

            add_experts_face_info(result["certificateNo"], data["phone_number"], data["faceData"], resp['data']['appointmentInfoList'][0]['orderId'])

            if data['role_id'] != 3:
                box, msg = handle_cabinet(result["certificateNo"], data["faceData"])
                if msg:
                    logger.bind(log_type='signin').error({"id_card": result["certificateNo"], "action": "储物柜下发权限", "data": msg})

                logger.bind(log_type='signin').error({"id_card": result["certificateNo"], "action": "储物柜信息", "data": box})

                if box:
                    key = f"{current_app.config['CABINET_LOCK']}{result['certificateNo']}_{box['position']}_{box['position_id']}_{box['row']}_{box['column']}_{box['ip_address']}"
                    g.redis_conn.setex(key, 60 * 3, "lock")

                _, msg = handle_room(data["room_ids"], result["certificateNo"], result["personName"], data["faceData"])

                if msg:
                    logger.bind(log_type='signin').error({"id_card": result["certificateNo"], "action": "会议室下发权限", "data": msg})
            else:
                box, msg = inspect_handle_cabinet(result["certificateNo"], data["faceData"])
                if msg:
                    logger.bind(log_type='signin').error({"id_card": result["certificateNo"], "action": "储物柜下发权限", "data": msg})

                logger.bind(log_type='signin').error({"id_card": result["certificateNo"], "action": "储物柜信息", "data": box})

                if box:
                    key = f"{current_app.config['CABINET_LOCK']}{result['certificateNo']}_{box['position']}_{box['position_id']}_{box['row']}_{box['column']}_{box['ip_address']}"
                    g.redis_conn.setex(key, 60 * 3, "lock")

        return response(resp['code'], resp['msg'], resp['data'])
    except Exception as e:
        logger.bind(log_type='error').error({"id_card": result["certificateNo"], "action": "访客预约失败", "data": e})
        return response(500, "服务器错误", {})


@hk_api.route("/api/person/single/add", methods=['POST'])
def person_single_add():
    """添加人员信息"""
    data = request.get_json()
    _, msg = validation.validate_fields(data, ["personName", "gender", "id_card", "faceData"])
    if msg:
        return response(422, msg, {})
    update_experts_face_info(data["id_card"], data["faceData"])
    res = single_person_add(data)
    logger.bind(log_type='signin').info({"id_card": data['id_card'], "action": "新增人员", "data": res})
    return response(res['code'], res['msg'], res['data'])


@hk_api.route("/api/visitor/order/register", methods=['POST'])
def visitor_order_register():
    """已预约登记"""
    data = request.get_json()

    _, msg = validation.validate_fields(data, ["orderId", "id_card"])
    if msg:
        return response(422, msg, {})

    res = order_register(data['orderId'])
    logger.bind(log_type='signin').info({"id_card": data['id_card'], "action": "预约登记", "data": res})
  
    with g.db_conn.cursor() as cursor:
        query = f"UPDATE {current_app.config['TABLE_PERSON']} SET hk_visitor_order_id = %s WHERE id_card = %s"
        cursor.execute(query, [data["orderId"], data["id_card"]])
        g.db_conn.commit()

    return response(res['code'], res['msg'], res['data'])
    

@hk_api.route("/api/visitor/out", methods=['POST'])
def visitor_out():
    """访客签离"""
    data = request.get_json()
    _, msg = validation.validate_fields(data, ["orderId", "id_card", "project_id", "room_ids", "role_id", "name"])
    if msg:
        return response(422, msg, {})

    # 访客签退
    res = visitor_sign_out_func(data)

    modify_updated_at(data.get('id_card'))
    
    box = info(data.get('id_card'))

    # 查询项目未签退的人员
    total = not_checkout(data.get('project_id'))

    # 判断当前项目中参加会议的人员是否已经全部签退，修改项目状态为已结束
    if total == 0:
        project_status(data.get('project_id'), 2)

    if data.get('role_id') != 3:
        # 删除人脸信息
        signout_handle_room(data.get('room_ids'), data.get('id_card'), data.get('name'))

    logger.bind(log_type='signout').info("🏒🏒🏒|" + ("-" * 50)  + "|" + data.get('id_card') + "|" + ("-" * 50) + "|")
       

    logger.bind(log_type='signout').info({"id_card": data["id_card"], "action": "释放柜子", "data": box})
        
    if box:
        # 触发 redis 1 秒后 解除人员锁定
        key = f"{current_app.config['CABINET_UNLOCK']}{data['id_card']}_{box['position']}_{box['position_id']}_{box['row']}_{box['column']}_{box['ip_address']}"
        g.redis_conn.setex(key, 1, "unlock")
        
        logger.bind(log_type='signout').info({"id_card": data["id_card"], "action": "解除人脸", "data": box})
        
        # 触发 redis 20 分钟后 删除人员，释放柜子权限
        delete_key = f"{current_app.config['CABINET_DELETE']}{data['id_card']}_{box['ip_address']}"
        g.redis_conn.setex(delete_key, 60 * current_app.config['CABINET_EXPIRES'], "delete")

        
        lock_key = f"{current_app.config['CABINET_LOCK']}{data['id_card']}_{box['position']}_{box['position_id']}_{box['row']}_{box['column']}_{box['ip_address']}"
        g.redis_conn.delete(lock_key)

    logger.bind(log_type='signout').info({"id_card": data["id_card"], "action": "访客签退", "data": res})

    if res['code'] == '0x0531f00e':
        return response(422, "根据参数无法查找到正确记录信息", {})

    return response(res['code'], res['msg'], res['data'])


@hk_api.route("/api/cabinet/lockSpace", methods=['POST'])
def lock_cabinet():
    """锁定柜子"""
    data = request.get_json()
    ip_address = data.pop('ip_address')
    auth = handle_auth(ip_address)
    url = f"http://{ip_address}/ISAPI/IntelligentCabinet/lockSpace?format=json"
    resp = httpx.put(url, auth=auth, data=orjson.dumps(data)).json()

    if ip_address == "192.168.100.119":
        cabinet_status()
    else:
        inspect_cabinet_status()
    return response(200, "success", resp)


@hk_api.route("/api/cabinet/unlockSpace", methods=['POST'])
def unlock_cabinet():
    """解锁柜子"""
    data = request.get_json()
    ip_address = data.pop('ip_address')
    auth = handle_auth(ip_address)
    url = f"http://{ip_address}/ISAPI/IntelligentCabinet/unlockSpace?format=json"
    resp = httpx.put(url, auth=auth, data=orjson.dumps(data)).json()
    
    if ip_address == "192.168.100.119":
        cabinet_status()
    else:
        inspect_cabinet_status()
    return response(200, "success", resp)


@hk_api.route("/api/cabinet/openSpace", methods=['POST'])
def open_cabinet():
    """开柜"""
    data = request.get_json()
    ip_address = data.pop('ip_address')
    auth = handle_auth(ip_address)
    url = f"http://{ip_address}/ISAPI/IntelligentCabinet/openSpace?format=json"
    resp = httpx.put(url, auth=auth, data=orjson.dumps(data)).json()
    
    if ip_address == "192.168.100.119":
        cabinet_status()
    else:
        inspect_cabinet_status()
    return response(200, "success", resp)